package main

import (
	"crypto/tls"
	"fmt"
	"io/ioutil"
	"math/rand"
	"net"
	"net/http"
	"net/url"
	"time"
)

func main() {
	{
		rsp, err := http.Get("http://www.baidu.com")
		if err == nil {
			_, err := ioutil.ReadAll(rsp.Body)
			if err != nil {
				panic(err)
			}
		}
		defer rsp.Body.Close()
	}

	{
		// start http server
		http.HandleFunc("/call", call)
		go http.ListenAndServe(":23456", nil)

		time.Sleep(time.Second)

		// start http request
		const (
			HTTP_REQUEST_CONN_TIMEOUT = 1 * time.Millisecond
			HTTP_REQUEST_CALL_TIMEOUT = 5 * time.Millisecond
		)

		transport := &http.Transport{
			Dial: func(netw, addr string) (net.Conn, error) {
				c, err := net.DialTimeout(netw, addr, HTTP_REQUEST_CONN_TIMEOUT)
				if err != nil {
					return nil, err
				}
				c.SetDeadline(time.Now().Add(HTTP_REQUEST_CALL_TIMEOUT))
				return c, nil
			},
			TLSClientConfig:   &tls.Config{InsecureSkipVerify: true},
			DisableKeepAlives: true,
		}

		clt := &http.Client{
			Transport: transport,
		}

		var data = url.Values{}
		data.Set("val", "10001")
		for i := 0; i < 10; i++ {
			fmt.Println("Start Call")
			rsp, err := clt.PostForm("http://localhost:23456/call", data)
			if err != nil {
				fmt.Println("Call Failed ERROR:", err)
			} else {
				fmt.Println("Call Success")
				rsp.Body.Close()
			}
			time.Sleep(time.Second)
			fmt.Println("Call End")
		}
	}

	{
		fmt.Println("Timeout Call:")
		clt := &http.Client{
			Timeout: 1 * time.Millisecond,
		}

		var data = url.Values{}
		data.Set("val", "10001")
		for i := 0; i < 10; i++ {
			fmt.Println("Start Call")
			rsp, err := clt.PostForm("http://localhost:23456/call", data)
			if err != nil {
				fmt.Println("Call Failed ERROR:", err)
			} else {
				fmt.Println("Call Success")
				rsp.Body.Close()
			}
			time.Sleep(time.Second)
			fmt.Println("Call End")
		}
	}

	var i int
	fmt.Scanf("%d", &i)
}

func call(w http.ResponseWriter, r *http.Request) {
	sleep := rand.Intn(4) + 3
	time.Sleep(time.Duration(sleep) * time.Millisecond)

	val := r.FormValue("val")
	fmt.Println("Sleep", sleep, "Millisecond, Get Param:", val)
}
